#ifndef QUAD_H
#define QUAD_H

#include "symbol.h"

typedef enum { 
	      	OP_EQUAL,  	// Comparaison ==
		OP_NEQUAL,	// Comparaison !=
		OP_INF,		// Comparaison <
		OP_INF_EQUAL,	// Comparaison <=
		OP_SUP,		// Comparaison >
		OP_SUP_EQUAL,	// Comparaison >=
	        OP_ASSIGN,	// Assignation par valeur :  a = b
		OP_ASSIGN_ADR,   // Assignation de l'adresse de arg1 : a = &b
		OP_ASSIGN_PTR,   // Assignation de arg1 à l'adresse pointé par res : *a = b
		OP_ASSIGN_VAL,   // Assignation de la valeur pointé par arg1 : a = *b
	        OP_ADD,		// Addition
	        OP_SUB,		// Soustraction
	        OP_MUL,		// Multiplication
	        OP_DIV, 	// Division
		OP_ABS, 	// Valeur absolue
		NUL_QUAD,	// QUAD NULL
		OP_GOTO,	// GOTO
		OP_PRINT_DIGIT,	// Affichage d'un entier
		OP_PRINT_STRING,// Affichage d'une chaine de caractère
		LABEL_END	// Label de fin END
} op_type;

/* Instruction à 3 adresses */
typedef struct quad {
	int label;			// Label de l'instruction
	op_type operateur;		// Type d'instruction
	symbol_table* arg1;		// argument 1
	symbol_table* arg2;  		// argument 2
	symbol_table* res;		// résultat
	int next;			// Label si il sagit d'un GOTO
} quad; 

/* Liste de quad */
typedef struct list_quad {
	struct quad* q;
	struct list_quad* next;	
} list_quad;

/* Structure pour gérer la complétion des adresses de GOTO pour les conditions et structures de controle */
typedef struct gen_quad {
	struct list_quad* vrai;
	struct list_quad* faux;
	struct list_quad* next;
} gen_quad;

typedef struct array_quad {
	symbol_table* array;
	symbol_table* ptr;
	int ndim;	
} array_quad;

/* 
 * Créer une liste vide 
 */
list_quad* creer_list_vide();

/* 
 * Créer une liste initialisé avec un quad 
 */
list_quad* creer_list(quad* q);

/*
 * Récupérer le dernier résultat de la liste de quads
 */
symbol_table* get_list_res(list_quad* l);

/* 
 * Concatène l2 dans l1 
 */
list_quad* concat(list_quad** l1, list_quad** l2);

/* 
 * Complete la liste de quad l avec l'adresse next_quad 
 */ 
void complete(list_quad** l,int next_quad);

/*  
 * Affichage d'un quad 
 */
void print_quad(quad* qd);

/* 
 * Affichage d'une liste de quad 
 */
void print_quad_list(list_quad* program);

/*
 * Génère une instruction à 3 adresse et l'ajoute à la list_quad lq.
 * Incrémente aussi next_quad 
 */
quad* gen_code(list_quad** lq,int* nextquad,int op, symbol_table* arg1,symbol_table* arg2,symbol_table* res,int next);
#endif
